package com.bing.util;

import com.bing.exception.WeiBoException;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Created by Administrator on 2014/6/20.
 */
public class TaoBao {
    private static final Logger logger = LoggerFactory.getLogger(TaoBao.class);
    public static String SCREEN_SHOT_DIR = System.getProperty("app.home") + "/screenShot/";

    private static ConcurrentMap<WebDriver, WebDriverWait> waitMap = new ConcurrentHashMap<WebDriver, WebDriverWait>();

    private static Random random = new Random();

    public static SimpleDateFormat sdf = new SimpleDateFormat("MM-dd_hh_mm");

    static {
        SCREEN_SHOT_DIR = SCREEN_SHOT_DIR + sdf.format(new Date()) + "";
    }

    /**
     * 截图
     *
     * @param driver
     * @param name
     */
    public static void screenShot(WebDriver driver, String key, String name, By by) {
        screenShot(driver, key, name, driver.findElement(by));
    }

    /**
     * 截图
     *
     * @param driver
     * @param name
     */
    public static void screenShot(WebDriver driver, String key, String name) {
        WebElement e = null;
        screenShot(driver, key, name, e);
    }

    /**
     * 截图
     *
     * @param driver
     * @param name
     */
    public static void screenShot(WebDriver driver, String key, String name, WebElement element) {
        File screenshot = null;
        try {
            name = name.replace("/", "-").replace(" ", "-");
            logger.info("开始截图: {}", name);
            int screenHeight = 0, screenWidth = 0;
            if (element != null) {
                int height = 5, width = 0;
                int left, top;
                scrollBar(driver, element);
                if (driver instanceof PhantomJSDriver || driver instanceof FirefoxDriver || driver instanceof InternetExplorerDriver) {
                    height = element.getSize().getHeight();
                    width = element.getSize().getWidth();
                    left = element.getLocation().getX();
                    top = element.getLocation().getY();
                } else {
                    height = element.getSize().getHeight();
                    width = element.getSize().getWidth();
                    top = Double.valueOf(((JavascriptExecutor) driver).executeScript("javascript:return arguments[0].getBoundingClientRect().top", element) + "").intValue();
                    left = Double.valueOf(((JavascriptExecutor) driver).executeScript("javascript:return arguments[0].getBoundingClientRect().left", element) + "").intValue();
                    logger.debug("截图参数 left:{}, top:{}, width:{}, height:{}, screenWidth:{},screenHeigh:{}", left, top, width, height, screenWidth, screenHeight);

                    screenHeight = Double.valueOf(((JavascriptExecutor) driver).executeScript("javascript:return document.documentElement.clientHeight") + "").intValue();
                    screenWidth = Double.valueOf(((JavascriptExecutor) driver).executeScript("javascript:return document.documentElement.clientWidth") + "").intValue();
                    width = screenWidth < (left + width) ? (screenWidth - left) : width;
                    height = screenHeight < (top + height) ? (screenHeight - top) : height;
                    logger.debug("截图参数2 left:{}, top:{}, width:{}, height:{}, screenWidth:{},screenHeigh:{}", left, top, width, height, screenWidth, screenHeight);
                    if (height == 0) {
                        height = screenHeight - top;
                    }
                }
                screenshot = ((RemoteWebDriver) driver).getScreenshotAs(OutputType.FILE);
                BufferedImage bufferedImage = ImageIO.read(screenshot);
                BufferedImage destImage = bufferedImage.getSubimage(left, top, width, height);
                ImageIO.write(destImage, "png", screenshot);
            } else {
                screenshot = ((RemoteWebDriver) driver).getScreenshotAs(OutputType.FILE);
                if (driver instanceof PhantomJSDriver || driver instanceof FirefoxDriver || driver instanceof InternetExplorerDriver) {
                    screenHeight = Double.valueOf(((JavascriptExecutor) driver).executeScript("javascript:return document.documentElement.clientHeight") + "").intValue();
                    screenWidth = Double.valueOf(((JavascriptExecutor) driver).executeScript("javascript:return document.documentElement.clientWidth") + "").intValue();
                    BufferedImage bufferedImage = ImageIO.read(screenshot);
                    BufferedImage destImage = bufferedImage.getSubimage(0, 0, screenWidth, screenHeight);
                    ImageIO.write(destImage, "png", screenshot);
                }
            }
            FileUtils.copyFile(screenshot, new File(SCREEN_SHOT_DIR + key + "/" + name + ".jpg"));
            logger.info("成功截图: {}", name);
        } catch (Exception e) {
            logger.error("截图失败...", e);
        } finally {
        }
    }

    public static void switchLast(WebDriver driver) {
        for (String handle : driver.getWindowHandles()) {
            driver.switchTo().window(handle);
        }
        logger.debug("切换到 Title: " + driver.getTitle());
    }

    public static List<WebElement> randomBaoBei(List<WebElement> bs, String id, boolean contain, int bihuoshu) {
        Assert.isTrue(bihuoshu <= bs.size(), "比货数要比总货数少");
        logger.info("寻找目标宝贝: {}", id);
        List<WebElement> baobeis = new ArrayList<WebElement>();
        WebElement mubiao = null;
        for (WebElement baobei : bs) {
            if (baobei.getAttribute("href").contains(id)) {
                logger.info("找到目标宝贝: {}", baobei.getAttribute("title"));
                mubiao = baobei;
                break;
            }
        }
        if (mubiao != null) {
            for (Integer i : TaoMath.getRandoms(bs.size(), bihuoshu > bs.size() ? bs.size() : bihuoshu)) {
                baobeis.add(bs.get(i));
            }
        } else {
            if (bs.size() >= 1) {
                for (Integer i : TaoMath.getRandoms(bs.size(), 1)) {
                    baobeis.add(bs.get(i));
                }
            }
        }
        if (contain) {
            baobeis.add(mubiao);
        } else {
            baobeis.remove(mubiao);
        }
        return baobeis;
    }

    public static void moveto(WebDriver driver, WebElement element) {
        Actions action = new Actions(driver);
        action.moveToElement(element).build().perform();
        pause(500);
    }

    public static void scrollBar(WebDriver driver, WebElement element) {
        JavascriptExecutor js = (JavascriptExecutor) driver;
        Double clientHeight = Double.valueOf(js.executeScript("javascript:return document.documentElement.clientHeight") + "");
        Double elementTop = Double.valueOf(js.executeScript("javascript:return arguments[0].getBoundingClientRect().top", element) + "");
        Double step = clientHeight / 9;
        Double oldElementTop = 0.0;
        logger.info("滚动步长: {}, 元素高度:{} 浏览器高度:{}", step, elementTop, clientHeight);

        if (elementTop < 0) {
            step = -step;
            while (elementTop < (-step + 60) && BigDecimal.valueOf(oldElementTop).compareTo(BigDecimal.valueOf(elementTop)) != 0) {
                oldElementTop = elementTop;
                js.executeScript("javascript:window.scrollBy(0, arguments[0])", step);
                //获取元素相对浏览器上边距离
                elementTop = Double.valueOf(js.executeScript("javascript:return arguments[0].getBoundingClientRect().top", element) + "");
                logger.debug("滚动: 元素高度{}, 旧高度:{}", elementTop, oldElementTop);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } else {
            while ((elementTop > (step + 60)) && BigDecimal.valueOf(oldElementTop).compareTo(BigDecimal.valueOf(elementTop)) != 0) {
                oldElementTop = elementTop;
                js.executeScript("javascript:window.scrollBy(0, arguments[0])", step);
                elementTop = Double.valueOf(js.executeScript("javascript:return arguments[0].getBoundingClientRect().top", element) + "");
                logger.debug("滚动: 元素高度{}, 旧高度:{}", elementTop, oldElementTop);


                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        logger.info("滚动后元素高度:{} ", elementTop);
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void scrollBar(WebDriver driver, By by) {
        WebElement element = driver.findElement(by);
        scrollBar(driver, element);
    }

    public static void pause(long times) {
        try {
            Thread.sleep(times);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static WebDriverWait getWait(WebDriver driver) {
        WebDriverWait wait = waitMap.get(driver);
        if (wait == null) {
            wait = new WebDriverWait(driver, 10);
            waitMap.put(driver, wait);
        }
        return wait;
    }

    public static void pause() {
        pause(1200 + random.nextInt(2) * 1000);
    }

    public static void pauseLong() {
        pause(3000 + random.nextInt(10) * 1000);
    }

    public static void handleException(Context context, Exception e) {
        if (e instanceof TimeoutException) {
            if (context.getDriver() != null) {
                context.getDriver().quit();
            }
            if (context.getTaoListener() != null) {
                context.getTaoListener().enableShua("刷一下");
                context.getTaoListener().setStatus("刷不成功,请重试");
            }

            throw new RuntimeException("刷刷出现问题");
        }
        if (e instanceof WeiBoException) {
            context.setSetting(Context.GONEXT, false);
            if (context.getDriver() != null) {
                context.getDriver().quit();
            }
            switch (e.getMessage()) {
                case Context.LOGIN_FAILED:
                    context.getTaoListener().enableShua("刷一下");
                    context.getTaoListener().setStatus("登入失败");
                    break;
                case Context.GETWEIBOFAILED:
                    context.getTaoListener().enableShua("刷一下");
                    context.getTaoListener().setStatus("采集微波失败");
                    break;
                case Context.GetFOLLOWFAILED:
                    break;

            }

        }
    }


    /**
     * Executes a script on an element
     *
     * @param script  The script to execute
     * @param element The target of the script, referenced as arguments[0]
     * @note Really should only be used when the web driver is sucking at exposing
     * functionality natively
     */
    public static void trigger(Context context, String script, WebElement element) {
        ((JavascriptExecutor) context.getDriver()).executeScript(script, element);
    }

    /**
     * Executes a script
     *
     * @param script The script to execute
     * @note Really should only be used when the web driver is sucking at exposing
     * functionality natively
     */
    public static Object trigger(Context context, String script) {
        return ((JavascriptExecutor) context.getDriver()).executeScript(script);
    }

    /**
     * Opens a new tab for the given URL
     *
     * @param url The URL to
     * @throws Exception If unable to open tab
     */
    public static void openTab(WebDriver driver, String url) {
        /*String script = "var d=document,a=d.createElement('a');a.target='_blank';a.href='%s';a.innerHTML='.';d.body.appendChild(a);return a";
        Object element = trigger(context, String.format(script, url));
        if (element instanceof WebElement) {
            WebElement anchor = (WebElement) element;
            anchor.click();
            trigger(context, "var a=arguments[0];a.parentNode.removeChild(a);", anchor);
        } else {
            throw new IllegalArgumentException();
        }
        switchLast(context.getDriver());*/


        String script = String.format("window.open('%s', '_blank');", url);
        ((JavascriptExecutor) driver).executeScript(script);
        switchLast(driver);
    }

    public static List<String> getWeiBoIds(String ids) {
        List<String> weiBos = new ArrayList<String>();
        if (ids.contains("/") || ids.contains("\\")) {
            try {
                File file = ResourceUtils.getFile(ids);
                BufferedReader reader = new BufferedReader(new FileReader(file));
                String tempString = null;
                // 一次读入一行，直到读入null为文件结束
                while ((tempString = reader.readLine()) != null) {
                    weiBos.add(tempString.trim());
                }
                reader.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

        } else {
            weiBos.add(ids);
        }
        return weiBos;
    }

}
